package org.chen.translate.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.chen.common.translate.dto.BaiduApiResponse;
import org.chen.common.translate.dto.BaiduTranslateRequestDTO;
import org.chen.common.translate.dto.BaiduTranslateResponseDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

@Service
public class BaiduTranslateService {

    private static final Logger logger = LoggerFactory.getLogger(BaiduTranslateService.class);

    // 百度翻译API配置
    @Value("${baidu.translate.appid:20250910002450849}")
    private String baiduAppId;

    @Value("${baidu.translate.appkey:wFAx2Chsrn6IoLj7sQt7}")
    private String baiduAppKey;

    @Value("${baidu.translate.api-url:https://fanyi-api.baidu.com/api/trans/vip/translate}")
    private String apiUrl;

    // 限流配置
    @Value("${baidu.translate.rate-limit.requests-per-second:10}")
    private int requestsPerSecond;

    @Value("${baidu.translate.rate-limit.max-retry-times:3}")
    private int maxRetryTimes;

    @Value("${baidu.translate.rate-limit.retry-delay-ms:1000}")
    private long retryDelayMs;

    @Value("${baidu.translate.rate-limit.max-wait-time-ms:30000}")
    private long maxWaitTimeMs;

    // 限流器组件
    private Semaphore rateLimiter;
    private final AtomicLong lastRequestTime = new AtomicLong(0);
    private long requestIntervalMs;

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    private final Random random;

    public BaiduTranslateService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
        this.objectMapper = new ObjectMapper();
        this.random = new Random();
    }

    @PostConstruct
    private void initRateLimiter() {
        this.rateLimiter = new Semaphore(requestsPerSecond);
        this.requestIntervalMs = 1000L / requestsPerSecond;
        logger.info("百度翻译限流器初始化完成，每秒最多{}个请求，请求间隔{}ms", requestsPerSecond, requestIntervalMs);
    }

    /**
     * 翻译文本
     * @param request 翻译请求
     * @return 翻译响应
     * @throws Exception 翻译异常
     */
    public BaiduTranslateResponseDTO translateText(BaiduTranslateRequestDTO request) throws Exception {
        return executeWithRateLimit(request);
    }

    /**
     * 带限流的翻译执行
     */
    private BaiduTranslateResponseDTO executeWithRateLimit(BaiduTranslateRequestDTO request) throws Exception {
        int retryCount = 0;
        Exception lastException = null;

        while (retryCount <= maxRetryTimes) {
            try {
                // 获取限流许可
                boolean acquired = rateLimiter.tryAcquire(maxWaitTimeMs, TimeUnit.MILLISECONDS);
                if (!acquired) {
                    throw new RuntimeException("系统繁忙，请稍后再试（等待超时）");
                }

                try {
                    // 确保请求间隔
                    enforceRequestInterval();

                    // 执行翻译
                    return performTranslation(request);

                } finally {
                    // 延迟释放许可
                    schedulePermitRelease();
                }

            } catch (Exception e) {
                lastException = e;

                // 判断是否需要重试
                if (shouldRetry(e) && retryCount < maxRetryTimes) {
                    retryCount++;
                    long delayMs = retryDelayMs * retryCount;

                    logger.warn("百度翻译第{}次重试，延迟{}ms。错误：{}",
                            retryCount, delayMs, e.getMessage());

                    try {
                        Thread.sleep(delayMs);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new RuntimeException("翻译被中断", ie);
                    }
                } else {
                    throw e;
                }
            }
        }

        if (lastException != null) {
            throw lastException;
        } else {
            throw new RuntimeException("翻译失败，已达到最大重试次数");
        }
    }

    /**
     * 执行实际的翻译请求 - 修复版本
     */
    private BaiduTranslateResponseDTO performTranslation(BaiduTranslateRequestDTO request) throws Exception {
        try {
            // 1. 生成随机salt
            String salt = generateSalt();

            // 2. 生成签名（关键：q参数不进行URL编码）
            String sign = generateSign(baiduAppId, request.getQ(), salt, baiduAppKey);

            // 3. 打印调试信息
            logger.debug("=== 百度翻译签名调试信息 ===");
            logger.debug("appid: {}", baiduAppId);
            logger.debug("q: {}", request.getQ());
            logger.debug("salt: {}", salt);
            logger.debug("appkey: {}", baiduAppKey);
            logger.debug("签名字符串: {}", baiduAppId + request.getQ() + salt + baiduAppKey);
            logger.debug("生成签名: {}", sign);

            // 4. 使用POST方式发送请求（推荐方式，避免GET URL长度限制）
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.set("User-Agent", "Mozilla/5.0 (Java BaiduTranslate Client)");

            // 5. 构建表单数据
            MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
            formData.add("q", request.getQ());              // RestTemplate会自动处理编码
            formData.add("from", request.getFromLang());
            formData.add("to", request.getToLang());
            formData.add("appid", baiduAppId);
            formData.add("salt", salt);
            formData.add("sign", sign);

            HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(formData, headers);

            logger.debug("发送POST请求到百度翻译API: {}", apiUrl);

            // 6. 发送POST请求
            ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                String responseBody = response.getBody();
                logger.debug("百度翻译API响应: {}", responseBody);

                // 解析响应
                BaiduApiResponse apiResponse = objectMapper.readValue(responseBody, BaiduApiResponse.class);

                // 检查是否有错误
                if (apiResponse.getErrorMsg() != null) {
                    String errorMsg = String.format("百度翻译API错误[%s]: %s",
                            apiResponse.getErrorCode(),
                            apiResponse.getErrorMsg());
                    throw new RuntimeException(errorMsg);
                }

                // 转换为标准响应格式
                BaiduTranslateResponseDTO result = new BaiduTranslateResponseDTO();
                result.setFrom(apiResponse.getFrom());
                result.setTo(apiResponse.getTo());
                result.setErrorCode(apiResponse.getErrorCode());
                result.setErrorMsg(apiResponse.getErrorMsg());
                result.setTransResult(apiResponse.getTransResult());

                logger.info("百度翻译成功，原文长度: {}, 译文数量: {}",
                        request.getQ().length(),
                        result.getTransResult() != null ? result.getTransResult().size() : 0);

                return result;

            } else {
                throw new RuntimeException("请求百度翻译API失败，状态码: " + response.getStatusCode());
            }

        } catch (Exception e) {
            logger.error("百度翻译执行失败: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 生成随机salt（5位数字）
     */
    private String generateSalt() {
        StringBuilder salt = new StringBuilder();
        for (int i = 0; i < 5; i++) {
            salt.append(random.nextInt(10));
        }
        return salt.toString();
    }

    /**
     * 生成MD5签名
     * 签名规则：appid + q + salt + appkey 的MD5值
     * 注意：q参数不进行URL编码
     */
    private String generateSign(String appid, String q, String salt, String appkey) {
        try {
            // 关键：签名生成时q参数不进行URL编码
            String signStr = appid + q + salt + appkey;
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(signStr.getBytes(StandardCharsets.UTF_8));

            StringBuilder hexString = new StringBuilder();
            for (byte b : digest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }

            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5算法不可用", e);
        }
    }

    /**
     * 确保请求间隔
     */
    private void enforceRequestInterval() {
        synchronized (this) {
            long currentTime = System.currentTimeMillis();
            long lastTime = lastRequestTime.get();
            long timeSinceLastRequest = currentTime - lastTime;

            if (timeSinceLastRequest < requestIntervalMs) {
                long sleepTime = requestIntervalMs - timeSinceLastRequest;
                try {
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }

            lastRequestTime.set(System.currentTimeMillis());
        }
    }

    /**
     * 延迟释放许可
     */
    private void schedulePermitRelease() {
        new Thread(() -> {
            try {
                Thread.sleep(requestIntervalMs);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                rateLimiter.release();
            }
        }).start();
    }

    /**
     * 判断是否应该重试
     */
    private boolean shouldRetry(Exception e) {
        String message = e.getMessage();
        if (message == null) return false;

        return message.contains("timeout") ||
                message.contains("connection") ||
                message.contains("network") ||
                message.contains("服务暂不可用") ||
                message.contains("54001"); // 百度翻译签名错误，可能是网络问题导致
    }

    /**
     * 获取限流状态
     */
    public String getRateLimitStatus() {
        return String.format("百度翻译限流状态 - 可用许可: %d/%d, 等待队列: %d, 上次请求间隔: %dms",
                rateLimiter.availablePermits(),
                requestsPerSecond,
                rateLimiter.getQueueLength(),
                System.currentTimeMillis() - lastRequestTime.get());
    }

    /**
     * 重置限流器
     */
    public void resetRateLimiter() {
        logger.warn("重置百度翻译限流器");
        this.rateLimiter = new Semaphore(requestsPerSecond);
        this.lastRequestTime.set(0);
    }
}